Skip to content

Conversation

@MishkaRogachev
Copy link
Contributor

@MishkaRogachev MishkaRogachev commented Dec 24, 2025

Fixes NIT-4152 and NIT-4253
pulls in OffchainLabs/nitro-precompile-interfaces#25
pulls in OffchainLabs/go-ethereum#604
pulls in OffchainLabs/nitro-testnode#173

Changes:

  • Add new precompile ArbFilteredTransactionsManager to manage filtered transactions
  • Add transaction censors to ArbOs and ArbOwner to limit access to ArbFilteredTransactionsManager
  • Add an account, separated from ArbOs state, to store filtered transactions
  • Limit filtered transactions feature with ArbCensoredTransactionManagerFromTime

@MishkaRogachev MishkaRogachev changed the title Add ArbCensoredTransactionsManager precompile (idle) Add ArbCensoredTransactionsManager precompile Dec 24, 2025
@MishkaRogachev MishkaRogachev force-pushed the create-arbcensoredtransactionsmanager-precompile branch from 1adc79f to 81f4e5e Compare December 24, 2025 14:55
@codecov
Copy link

codecov bot commented Dec 24, 2025

Codecov Report

❌ Patch coverage is 28.17680% with 130 lines in your changes missing coverage. Please review.
✅ Project coverage is 32.68%. Comparing base (33df7ee) to head (140c32e).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4174      +/-   ##
==========================================
- Coverage   32.69%   32.68%   -0.02%     
==========================================
  Files         467      469       +2     
  Lines       56373    56512     +139     
==========================================
+ Hits        18433    18472      +39     
- Misses      34720    34819      +99     
- Partials     3220     3221       +1     

@github-actions
Copy link
Contributor

github-actions bot commented Dec 24, 2025

❌ 3 Tests Failed:

Tests completed Failed Passed Skipped
3915 3 3912 0
View the top 3 failed tests by shortest run time
TestNitroNodeVersionAlerter
Stack Traces | 0.850s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
INFO [01-20|12:18:29.763] Updated payload                          id=0x03c3b8a3d78d05c9 number=23  hash=7ba78e..aed187 txs=1   withdrawals=0 gas=1,215,789  fees=1.215789e-06   root=09aab0..f6b274 elapsed=1.842ms
WARN [01-20|12:18:29.763] Sequencer ReadFromTxQueueTimeout is higher than MaxBlockSpeed ReadFromTxQueueTimeout=1s MaxBlockSpeed=10ms
INFO [01-20|12:18:29.764] Stopping work on payload                 id=0x03c3b8a3d78d05c9 reason=delivery
WARN [01-20|12:18:29.764] Sequencer ReadFromTxQueueTimeout is higher than MaxBlockSpeed ReadFromTxQueueTimeout=1s MaxBlockSpeed=10ms
INFO [01-20|12:18:29.764] State scheme set by user                 scheme=path
INFO [01-20|12:18:29.764] Starting work on payload                 id=0x03ec4f93cabb4b85
WARN [01-20|12:18:29.764] Getting file info                        dir= error="stat : no such file or directory"
INFO [01-20|12:18:29.765] Imported new potential chain segment     number=23  hash=7ba78e..aed187 blocks=1  txs=1   mgas=1.216  elapsed=1.315ms     mgasps=924.208  triediffs=86.29KiB  triedirty=0.00B
INFO [01-20|12:18:29.765] Updated payload                          id=0x03ec4f93cabb4b85 number=68  hash=a15c5b..638652 txs=1   withdrawals=0 gas=21000      fees=0.002099560704 root=0dba57..0a3455 elapsed="723.709µs"
INFO [01-20|12:18:29.765] Chain head was updated                   number=23  hash=7ba78e..aed187 root=09aab0..f6b274 elapsed="271.556µs"
INFO [01-20|12:18:29.765] Stopping work on payload                 id=0x03ec4f93cabb4b85 reason=delivery
INFO [01-20|12:18:29.766] DA providers configured                  totalWriters=0
WARN [01-20|12:18:29.766] validation not supported                 err="no validator url specified"
INFO [01-20|12:18:29.766] Started log indexer
INFO [01-20|12:18:29.766] Imported new potential chain segment     number=68  hash=a15c5b..638652 blocks=1  txs=1   mgas=0.021  elapsed="980.544µs" mgasps=21.417   triediffs=331.95KiB triedirty=0.00B
INFO [01-20|12:18:29.767] Chain head was updated                   number=68  hash=a15c5b..638652 root=0dba57..0a3455 elapsed="75.29µs"
INFO [01-20|12:18:29.767] Starting peer-to-peer node               instance=test-stack-name/linux-amd64/go1.25.5
WARN [01-20|12:18:29.767] P2P server will be useless, neither dialing nor listening
WARN [01-20|12:18:29.768] Getting file info                        dir= error="stat : no such file or directory"
--- FAIL: TestNitroNodeVersionAlerter (0.85s)
TestVersion40
Stack Traces | 5.940s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
        github.com/offchainlabs/nitro/system_tests.Require(0xc0a44868c0, {0x403d120, 0xc0a1b7cc60}, {0x0, 0x0, 0x0})
        	/home/runner/work/nitro/nitro/system_tests/common_test.go:2041 +0x5d
        github.com/offchainlabs/nitro/system_tests.testPrecompiles(0xc0a44868c0, 0x28, {0xc08869ddf8, 0x5, 0x39?})
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:94 +0x371
        github.com/offchainlabs/nitro/system_tests.TestVersion40(0xc0a44868c0?)
        	/home/runner/work/nitro/nitro/system_tests/precompile_inclusion_test.go:71 +0x64b
        testing.tRunner(0xc0a44868c0, 0x3cc0880)
        	/opt/hostedtoolcache/go/1.25.5/x64/src/testing/testing.go:1934 +0xea
        created by testing.(*T).Run in goroutine 1
        	/opt/hostedtoolcache/go/1.25.5/x64/src/testing/testing.go:1997 +0x465
        
    precompile_inclusion_test.go:94: �[31;1m [] execution aborted (timeout = 5s) �[0;0m
INFO [01-20|12:15:42.907] Writing cached state to disk             block=1  hash=42cfe6..b682c4 root=d45d64..4e7811
INFO [01-20|12:15:42.907] Persisted trie from memory database      nodes=23  flushnodes=0 size=3.61KiB   flushsize=0.00B time="170.007µs" flushtime=0s gcnodes=0 gcsize=0.00B gctime="1.702µs"  livenodes=0   livesize=0.00B
INFO [01-20|12:15:42.907] Writing cached state to disk             block=1  hash=42cfe6..b682c4 root=d45d64..4e7811
INFO [01-20|12:15:42.907] Persisted trie from memory database      nodes=0   flushnodes=0 size=0.00B     flushsize=0.00B time=852ns       flushtime=0s gcnodes=0 gcsize=0.00B gctime=0s         livenodes=0   livesize=0.00B
INFO [01-20|12:15:42.907] Writing snapshot state to disk           root=28fb26..40a768
INFO [01-20|12:15:42.907] Persisted trie from memory database      nodes=0   flushnodes=0 size=0.00B     flushsize=0.00B time=380ns       flushtime=0s gcnodes=0 gcsize=0.00B gctime=0s         livenodes=0   livesize=0.00B
INFO [01-20|12:15:42.907] Blockchain stopped
--- FAIL: TestVersion40 (5.94s)
TestSequencerInboxReader
Stack Traces | 25.850s run time
... [CONTENT TRUNCATED: Keeping last 20 lines]
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=b46be2..129282 parent=055e98..8d6404 id=115                block=114
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=145ca4..c98375 parent=b46be2..129282 id=116                block=115
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=b8e0e7..2912bc parent=145ca4..c98375 id=117                block=116
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=25af8b..2f7cbb parent=b8e0e7..2912bc id=118                block=117
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=70552f..682a51 parent=25af8b..2f7cbb id=119                block=118
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=766cc0..f018db parent=70552f..682a51 id=120                block=119
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=468073..dd2a98 parent=766cc0..f018db id=121                block=120
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=ef33e1..cd6b08 parent=468073..dd2a98 id=122                block=121
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=1834de..a9d808 parent=ef33e1..cd6b08 id=123                block=122
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=fa9ab8..32d3c2 parent=1834de..a9d808 id=124                block=123
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=766fec..533e6a parent=fa9ab8..32d3c2 id=125                block=124
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=e92ca1..acd52b parent=766fec..533e6a id=126                block=125
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=25df5f..49ff97 parent=e92ca1..acd52b id=127                block=126
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=659232..452219 parent=25df5f..49ff97 id=128                block=127
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=0da6ef..722dd3 parent=659232..452219 id=129                block=128
DEBUG[01-20|12:12:27.228] Journaled pathdb diff layer              root=ba5d04..803e3b parent=0da6ef..722dd3 id=130                block=129
INFO [01-20|12:12:27.242] Persisted dirty state to disk            size=591.74KiB elapsed=18.779ms
INFO [01-20|12:12:27.242] Blockchain stopped
TRACE[01-20|12:12:27.242] P2P networking is spinning down
--- FAIL: TestSequencerInboxReader (25.85s)

📣 Thoughts on this report? Let Codecov know! | Powered by Codecov

@MishkaRogachev MishkaRogachev force-pushed the create-arbcensoredtransactionsmanager-precompile branch 2 times, most recently from 45fb413 to 67c13f2 Compare December 26, 2025 15:01
@MishkaRogachev MishkaRogachev changed the title Add ArbCensoredTransactionsManager precompile Add ArbFilteredTransactionsManager precompile Dec 26, 2025
@MishkaRogachev MishkaRogachev force-pushed the create-arbcensoredtransactionsmanager-precompile branch 3 times, most recently from 7b7a735 to f56f36c Compare December 29, 2025 12:06
@MishkaRogachev MishkaRogachev marked this pull request as ready for review December 29, 2025 13:48
@Tristan-Wilson Tristan-Wilson self-assigned this Dec 29, 2025
Copy link
Member

@Tristan-Wilson Tristan-Wilson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just a minor comment about consistency of the interface with other precompiles.

return filteredState.IsFiltered(txHash)
}

func (con ArbFilteredTransactionsManager) hasAccess(c *Context) (bool, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This signature is slightly different to ArbNativeTokenManager which has

func (con ArbNativeTokenManager) hasAccess(c ctx) bool {
	manager, err := c.State.NativeTokenOwners().IsMember(c.caller)
	return manager && err == nil
}

and therefore the behavior when there is an error is slightly different in this implementation in that if there is an error, then the gas is not burned out.

Unsure if this difference is intentional or not.

@Tristan-Wilson
Copy link
Member

Tristan-Wilson commented Dec 29, 2025

We should consider making ArbFilteredTransactionsManager calls free for transaction censors, similar to how ArbOwner calls are free for chain owners. Currently, censors pay gas for AddFilteredTransaction/DeleteFilteredTransaction, but since they're trusted actors authorized by chain owners, it would make sense to follow the same pattern. This could be done by creating a CensorPrecompile wrapper (similar to OwnerPrecompile in wrapper.go) that checks TransactionCensors().IsMember(caller) and returns gasSupplied with multigas.ZeroGas() on success.

@MishkaRogachev
Copy link
Contributor Author

This could be done by creating a CensorPrecompile wrapper (similar to OwnerPrecompile in wrapper.go) that checks TransactionCensors().IsMember(caller) and returns gasSupplied with multigas.ZeroGas() on success.

@Tristan-Wilson, wdyt about going further: remove ArbNativeToken-style check and return an error right in CensorPrecompile, like in ArbOwner?

"github.com/offchainlabs/nitro/solgen/go/precompilesgen"
)

func TestManageTransactionCensors(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please also test that the transactions that should be free are free? You can look at TestArbNativeTokenManager and getGasUsed inside it for inspiration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really get how to use getGasUsed in this case, since the transaction will still cost something, only the add/delete call is free. I can suggest to use multigas like this:

	tx, err = arbFilteredTxs.AddFilteredTransaction(&censorTxOpts, txHash)
   require.NoError(t, err)
   receipt, err := builder.L2.EnsureTxSucceeded(tx)
   require.NoError(t, err)

   require.Equal(t, uint64(0), receipt.MultiGasUsed.Get(multigas.ResourceKindStorageAccess))

This somehow proves that tx did not perform any storage operations like set and clear

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you check the censor account's balance is unchanged after adding/deleting filtered txs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This precompile wrapper does not make the transaction completely free, but I still believe that this test is useful because it allows to verify that the call goes through the wrapper

gligneul
gligneul previously approved these changes Jan 19, 2026
gligneul
gligneul previously approved these changes Jan 19, 2026
@MishkaRogachev MishkaRogachev assigned eljobe and unassigned tsahee Jan 20, 2026
### Added
- Add new precompile ArbFilteredTransactionsManager to manage filtered transactions
- Add transaction filterers to ArbOwner to limit access to ArbFilteredTransactionsManager
- Limit ArbOwners ability to create transaction filterers with TransactionFilteringFromTime
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: ArbOwners -> ArbOwners'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


// GetAllTransactionFilterers retrieves the list of transaction filterers
func (con ArbOwnerPublic) GetAllTransactionFilterers(c ctx, evm mech) ([]common.Address, error) {
return c.State.TransactionFilterers().AllMembers(65536)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this magic number? 65536?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same magic limiter exist in a few more places, replaced all with maxGetAllMembers

ArbOwnerPublic.methodsByName["IsNativeTokenOwner"].arbosVersion = params.ArbosVersion_41
ArbOwnerPublic.methodsByName["GetAllNativeTokenOwners"].arbosVersion = params.ArbosVersion_41
ArbOwnerPublic.methodsByName["GetParentGasFloorPerToken"].arbosVersion = params.ArbosVersion_50
ArbOwnerPublic.methodsByName["GetMaxStylusContractFragments"].arbosVersion = params.ArbosVersion_60
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this change have anything to do with StylusContractFragments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The StylusContractFragments precompile interface was already merged, but nitro PR not yet

@eljobe eljobe assigned MishkaRogachev and unassigned eljobe Jan 20, 2026
eljobe
eljobe previously approved these changes Jan 20, 2026
@eljobe eljobe added this pull request to the merge queue Jan 20, 2026
Merged via the queue into master with commit eb41575 Jan 20, 2026
23 of 24 checks passed
@eljobe eljobe deleted the create-arbcensoredtransactionsmanager-precompile branch January 20, 2026 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants